home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
4_0
/
GIFFEN.C
< prev
next >
Wrap
Text File
|
1990-02-28
|
9KB
|
364 lines
/*
GIF decompression for the Mac - put together by Kevin Parichan
using code and information from
David Rowley and Mac Tech Note #120
*/
#include <ColorToolbox.h>
#define NULL 0L
/********************************/
/* global variables */
/********************************/
Ptr dataPtr,saveDataPtr,Raster;
int ImageWidth,ImageHeight;
int HasColorMap;
long BitsPerPixel,ColorMapSize,BitMask;
long ReadMask,CodeSize;
long BitOffset = 0;
long OutCount = 0;
long Pass = 0;
int XC = 0;
int YC = 0;
int Interlace;
int Prefix[4096];
int Suffix[4096];
int OutCode[1025];
PaletteHandle thePalette = NULL;
CWindowPtr window;
long offRowBytes;
Ptr myBits;
/********************************/
/* #defines */
/********************************/
#define NEXTCHAR (*dataPtr++)
#define NEXTBYTE (NEXTCHAR & 0xFF)
#define NEXTSHORT (NEXTBYTE + (0x100 * NEXTBYTE))
#define IMAGESEP 0x2C
#define INTERLACEMASK 0x40
#define COLORMAPMASK 0x80
#define palWindowSize 10
#define RASTER(bo) (Raster[bo] & 0xFF)
/********************************/
/* routines */
/********************************/
long ReadCode()
{
long RawCode,ByteOffset;
ByteOffset = BitOffset / 8;
RawCode = RASTER(ByteOffset) + (0x100 * RASTER(ByteOffset + 1));
if (CodeSize >= 8)
RawCode += (0x10000 * RASTER(ByteOffset + 2));
RawCode >>= (BitOffset % 8);
BitOffset += CodeSize;
return(RawCode & ReadMask);
}
AddToPixel(int index)
{
myBits[YC*offRowBytes+XC] = (index & 0xFF);
if (++XC == ImageWidth) {
XC = 0;
if (!Interlace)
YC++;
else {
switch (Pass) {
case 0:
YC += 8;
if (YC >= ImageHeight) {
Pass++;
YC = 4;
}
break;
case 1:
YC += 8;
if (YC >= ImageHeight) {
Pass++;
YC = 2;
}
break;
case 2:
YC += 4;
if (YC >= ImageHeight) {
Pass++;
YC = 1;
}
break;
case 3:
YC += 2;
break;
default:
break;
}
}
}
}
typedef BitMap *BitMapPtr;
ReadGIF(Str255 fName, int vRefNum)
{
long fileSize,sizeOfOff;
int ch,i,x,y,ch1,refNum,theDepth;
int ImageLeft,ImageTop,ImageFlags;
RGBColor color;
Rect aRect,bRect,globRect;
long ClearCode,EOFCode,FreeCode,FirstFree;
long InitCodeSize,MaxCode,Code;
long CurCode,OldCode,FinChar,InCode;
Ptr ptr1;
OSErr error;
CGrafPort myCGrafPort;
CGrafPtr myCGrafPtr;
CTabHandle ourCMHandle;
GDHandle theMaxDevice,oldDevice;
Point tempP;
Str255 signature;
BitOffset = OutCount = Pass = XC = YC = 0; /* reset stuff */
if (FSOpen(fName,vRefNum,&refNum)) return;
if (GetEOF(refNum,&fileSize)) { FSClose(refNum); return; }
if ((dataPtr = saveDataPtr = Raster = NewPtr(fileSize)) == NULL) { FSClose(refNum); return; }
if (FSRead(refNum,&fileSize,dataPtr)) { DisposPtr(saveDataPtr); FSClose(refNum); return; }
FSClose(refNum);
signature[0] = 6;
for (i = 1; i <= 6; i++)
signature[i] = NEXTBYTE;
if (!EqualString(signature,"\pGIF87a",TRUE,TRUE)) { DisposPtr(saveDataPtr); return; }
NEXTSHORT; /* ignore screen width */
NEXTSHORT; /* ignore screen height */
ch = NEXTBYTE;
HasColorMap = ((ch & COLORMAPMASK) ? TRUE : FALSE);
BitsPerPixel = (ch & 7) + 1;
ColorMapSize = 1 << BitsPerPixel;
BitMask = ColorMapSize - 1;
NEXTBYTE; /* ignore background color */
NEXTBYTE; /* end of GIF header */
if (HasColorMap && ((thePalette = NewPalette(ColorMapSize,NULL,pmTolerant,0)) != NULL))
for (i = 0; i < ColorMapSize; i++) {
color.red = NEXTBYTE * 257;
color.green = NEXTBYTE * 257;
color.blue = NEXTBYTE * 257;
SetEntryColor(thePalette,i,&color);
}
if (NEXTBYTE != IMAGESEP) {
if (thePalette != NULL) DisposePalette(thePalette);
DisposPtr(saveDataPtr);
return;
}
ImageLeft = NEXTSHORT;
ImageTop = NEXTSHORT;
ImageWidth = NEXTBYTE;
ImageWidth = ImageWidth + (NEXTBYTE * 0x100);
ImageHeight = NEXTBYTE;
ImageHeight = ImageHeight + (NEXTBYTE * 0x100);
ImageFlags = NEXTBYTE;
Interlace = ((ImageFlags & INTERLACEMASK) ? TRUE : FALSE);
SetRect(&aRect,0,0,palWindowSize*16+1,palWindowSize*16+1);
OffsetRect(&aRect,60,60);
window = (CWindowPtr)NewCWindow(NULL,&aRect,'',TRUE,3,(Ptr)(-1),FALSE,0);
SetPort(window);
if (thePalette != NULL) {
SetPalette(window,thePalette,TRUE);
ActivatePalette(window);
}
aRect = window->portRect;
for (i = 0 ; i < ColorMapSize ; i++)
{
PmForeColor(i);
x = (i % 16) * ((aRect.right-aRect.left) / 16) + 1;
y = (i / 16) * ((aRect.bottom-aRect.top) / 16) + 1;
SetRect(&bRect,x,y,x+((aRect.right-aRect.left) / 16) - 1,y + ((aRect.right-aRect.left) / 16) - 1);
PaintRect(&bRect);
}
while (!Button()) ;
while (Button()) ;
DisposeWindow(window);
SetCursor(*GetCursor(watchCursor));
SetRect(&aRect,0,0,ImageWidth,ImageHeight);
bRect = aRect;
OffsetRect(&aRect,10,30);
window = (CWindowPtr)NewCWindow(NULL,&aRect,'',TRUE,3,(Ptr)(-1),FALSE,0);
SetPort(window);
if (thePalette != NULL) {
SetPalette(window,thePalette,TRUE);
ActivatePalette(window);
}
globRect = bRect;
tempP.v = globRect.top;
tempP.h = globRect.left;
LocalToGlobal(&tempP);
globRect.top = tempP.v;
globRect.left = tempP.h;
tempP.v = globRect.bottom;
tempP.h = globRect.right;
LocalToGlobal(&tempP);
globRect.bottom = tempP.v;
globRect.right = tempP.h;
theMaxDevice = GetMaxDevice(&globRect);
oldDevice = GetGDevice();
SetGDevice(theMaxDevice);
myCGrafPtr = &myCGrafPort;
OpenCPort(myCGrafPtr);
theDepth = (**(*myCGrafPtr).portPixMap).pixelSize;
offRowBytes = (((theDepth * ImageWidth) + 15) >> 4) << 1;
sizeOfOff = (long)ImageHeight * offRowBytes;
myBits = NewPtr(sizeOfOff);
(**(*myCGrafPtr).portPixMap).baseAddr = myBits;
(**(*myCGrafPtr).portPixMap).rowBytes = offRowBytes + 0x8000;
(**(*myCGrafPtr).portPixMap).bounds = bRect;
ourCMHandle = (**(**theMaxDevice).gdPMap).pmTable;
if (HandToHand(&ourCMHandle) != noErr) {
CloseCPort(myCGrafPtr);
SetGDevice(oldDevice);
if (thePalette != NULL) DisposePalette(thePalette);
DisposPtr(saveDataPtr);
return;
}
for (i = 0; i <= (**ourCMHandle).ctSize; ++i)
(**ourCMHandle).ctTable[i].value = i;
(**ourCMHandle).ctFlags &= 0x7FFF;
(**ourCMHandle).ctSeed = GetCTSeed();
if (thePalette != NULL)
Palette2CTab(thePalette,ourCMHandle);
(**(*myCGrafPtr).portPixMap).pmTable = ourCMHandle;
SetPort(myCGrafPtr);
CodeSize = NEXTBYTE;
ClearCode = (1 << CodeSize);
EOFCode = ClearCode + 1;
FreeCode = FirstFree = ClearCode + 2;
CodeSize++;
InitCodeSize = CodeSize;
MaxCode = (1 << CodeSize);
ReadMask = MaxCode - 1;
ptr1 = Raster;
do {
ch = ch1 = NEXTBYTE;
while (ch--) *ptr1++ = NEXTBYTE;
} while (ch1);
Code = ReadCode();
while (Code != EOFCode) {
if (Code == ClearCode) {
CodeSize = InitCodeSize;
MaxCode = (1 << CodeSize);
ReadMask = MaxCode - 1;
FreeCode = FirstFree;
CurCode = OldCode = Code = ReadCode();
FinChar = CurCode & BitMask;
AddToPixel(FinChar);
}
else {
CurCode = InCode = Code;
if (CurCode >= FreeCode) {
CurCode = OldCode;
OutCode[OutCount++] = FinChar;
}
while (CurCode > BitMask) {
OutCode[OutCount++] = Suffix[CurCode];
CurCode = Prefix[CurCode];
}
FinChar = CurCode & BitMask;
OutCode[OutCount++] = FinChar;
for (i = OutCount - 1; i >= 0; i--)
AddToPixel(OutCode[i]);
OutCount = 0;
Prefix[FreeCode] = OldCode;
Suffix[FreeCode] = FinChar;
OldCode = InCode;
FreeCode++;
if (FreeCode >= MaxCode) {
if (CodeSize < 12) {
CodeSize++;
MaxCode *= 2;
ReadMask = (1 << CodeSize) - 1;
}
}
}
Code = ReadCode();
}
DisposPtr(saveDataPtr);
SetPort(window);
SetGDevice(oldDevice);
CopyBits((BitMapPtr)*(*myCGrafPtr).portPixMap,(BitMapPtr)*(*window).portPixMap,&bRect,&bRect,0,0L);
CloseCPort(myCGrafPtr);
DisposPtr(myBits);
DisposHandle(ourCMHandle);
InitCursor();
while (!Button()) ;
while (Button()) ;
DisposeWindow(window);
if (thePalette != NULL)
DisposePalette(thePalette);
}
MainLoop()
{
Point where = {80,80};
SFTypeList typeList;
SFReply reply;
typeList[0] = 'GIFf';
do {
SFGetFile(where,'',NULL,1,&typeList,NULL,&reply);
if (reply.good)
ReadGIF(reply.fName,reply.vRefNum);
} while (reply.good);
}
SetupMacintosh()
{
MaxApplZone();
MoreMasters();
MoreMasters();
MoreMasters();
MoreMasters();
InitGraf(&thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(NULL);
}
main()
{
SetupMacintosh();
InitCursor();
MainLoop();
}